﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;

namespace Dycox.Validation
{
    public class PropertyValueValidator : Validator
    {
        public PropertyValueValidator(string propertyName, Validator validator)
        {
            if (string.IsNullOrEmpty(propertyName))
                throw new ArgumentNullException("propertyName");
            if (validator == null)
                throw new ArgumentNullException("validator");

            _propertyName = propertyName;
            _innerValidator = validator;
        }

        private string _propertyName;
        [DefaultValue((string)null)]
        public string PropertyName
        {
            get { return _propertyName; }
        }

        private Validator _innerValidator;

        public Validator InnerValidator
        {
            get { return _innerValidator; }
        }

        protected internal override ValidationResult IsValid(object instance, PropertyValidationContext context)
        {
            if (instance == null)
                return ValidationResult.Ignore;

            if (context == null)
                context = CreateContext(instance);

            object value = Dycox.Utils.DataBinderUtil.Eval(instance, _propertyName);

            OnValidating(new ValidationEventArgs(value));

            return _innerValidator.IsValid(value, context);
        }

        public override Dycox.Validation.ValidationResult IsValid(object instance)
        {
            return IsValid(instance, null);
        }

        private PropertyValidationContext CreateContext(object value)
        {
            if (value == null)
                throw new ArgumentNullException("value");

            PropertyDescriptor prop;
            if (_propertyName.IndexOfAny(Dycox.Utils.DataBinderUtil.Separators) < 0)
            {
                prop = TypeDescriptor.GetProperties(value).Find(_propertyName, false);
                if (prop == null)
                    throw new InvalidOperationException("Property " + _propertyName + " not found on  " + value.GetType().FullName);
            }
            else
                prop = null;

            return new PropertyValidationContext(value, prop);
        }

    }

}
